package algotrader.fakeserver;

import java.util.List;

import quickfix.Application;
import quickfix.DoNotSend;
import quickfix.FieldNotFound;
import quickfix.IncorrectDataFormat;
import quickfix.IncorrectTagValue;
import quickfix.Message;
import quickfix.MessageCracker;
import quickfix.RejectLogon;
import quickfix.Session;
import quickfix.SessionID;
import quickfix.SessionNotFound;
import quickfix.UnsupportedMessageType;
import quickfix.field.AvgPx;
import quickfix.field.ClOrdID;
import quickfix.field.CumQty;
import quickfix.field.ExecID;
import quickfix.field.ExecTransType;
import quickfix.field.ExecType;
import quickfix.field.LeavesQty;
import quickfix.field.OrdStatus;
import quickfix.field.OrderID;
import quickfix.field.OrderQty;
import quickfix.field.OrigClOrdID;
import quickfix.field.Side;
import quickfix.field.Symbol;
import quickfix.fix42.ExecutionReport;
import quickfix.fix42.MarketDataIncrementalRefresh;
import quickfix.fix42.MarketDataSnapshotFullRefresh;
import quickfix.fix42.NewOrderSingle;
import quickfix.fix42.OrderCancelReject;
import quickfix.fix42.OrderCancelReplaceRequest;
import quickfix.fix42.OrderCancelRequest;
import algotrader.IFixApplication;
import algotrader.OperadorPregao;
import algotrader.Order;
import algotrader.book.Book;
import algotrader.book.BookLine;
import algotrader.book.BookManager;
import algotrader.book.BookRequester;

public class FakeAcceptorFixApplication extends MessageCracker implements IFixApplication, Application,BookRequester {
	private int execID=0;
	private BookManager bookManager;
	private FakeServerObserver observer;
	private SessionID session;
	
	public void onMessage(quickfix.fix42.MarketDataRequest data, SessionID sessionID) {
		observer.receiveMarketDataRequest(data);
	}
	
	public void onMessage(quickfix.fix42.NewOrderSingle order, SessionID sessionID) {
		System.out.println("Recebendo new order single");
		observer.receiveNewOrderSingle(order);
	}
	
	public void onMessage(quickfix.fix42.OrderCancelRequest order, SessionID sessionID) {
		System.out.println("Recebendo new order single");
		observer.receiveOrderCancelRequest(order);
	}
	
	public void onMessage(quickfix.fix42.OrderCancelReplaceRequest order, SessionID sessionID) {
		System.out.println("Recebendo new order single");
		observer.receiveOrderCancelReplaceRequest(order);
	}
	
	@Override
	public void receiveMarketData(Book book) {
		bookManager.receiveBook(book);
	}

	@Override
	public void requestBook(String string, BookManager bookManager) {
		this.bookManager = bookManager;
	}

	@Override
	public void receiveUpdateMarketData(BookLine bookLine) {
		bookManager.receiveBookLine(bookLine);
	}

	@Override
	public void receiveUpdateMarketData(List<BookLine> bls) {
		for(BookLine bl :bls)
			bookManager.receiveBookLine(bl);
	}

	@Override
	public void removeBookLine(BookLine bookLine) {
		bookManager.removeBookLine(bookLine);
	}

	@Override
	public void fromAdmin(Message arg0, SessionID arg1) throws FieldNotFound,
			IncorrectDataFormat, IncorrectTagValue, RejectLogon {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fromApp(Message message, SessionID sessionID) throws FieldNotFound,
			IncorrectDataFormat, IncorrectTagValue, UnsupportedMessageType {
		crack(message, sessionID);
	}

	@Override
	public void onCreate(SessionID arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onLogon(SessionID arg0) {
		this.session = arg0;
	}

	@Override
	public void onLogout(SessionID arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void toAdmin(Message arg0, SessionID arg1) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void toApp(Message arg0, SessionID arg1) throws DoNotSend {
		// TODO Auto-generated method stub
		
	}

	public void setObserver(FakeServerObserver fakeServerObserver) {
		this.observer = fakeServerObserver;
	}

	public void sendMarketDataSnapshot(
			MarketDataSnapshotFullRefresh msg) {
		try {
			Session.sendToTarget(msg,session);
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
	}

	public void sendMarketDataIncrementalRefresh(
			MarketDataIncrementalRefresh createIncrementalRefresh) {
		
	}

	@Override
	public void cancelOrder(Order compra) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void sendOrder(Order o) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void solicitaCancelamento(Order compra) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setOperadorPregao(OperadorPregao operadorPregao) {
		// TODO Auto-generated method stub
		
	}

	public void registerOrder(quickfix.fix42.NewOrderSingle newOrder) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('0'));
			e.set(new ExecType('0'));
			e.set(new OrdStatus('0'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(newOrder.get(new OrderQty()).getValue()));
			e.set(new CumQty(0));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void executeOrder(NewOrderSingle newOrder) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('0'));
			e.set(new ExecType('2'));
			e.set(new OrdStatus('2'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(0));
			e.set(new CumQty(newOrder.get(new OrderQty()).getValue()));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void parcialExecuteOrder(NewOrderSingle newOrder, double i) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('0'));
			e.set(new ExecType('1'));
			e.set(new OrdStatus('1'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(newOrder.get(new OrderQty()).getValue()-i));
			e.set(new CumQty(i));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void triggerStopLimitOrder(NewOrderSingle newOrder) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('0'));
			e.set(new ExecType('L'));
			e.set(new OrdStatus('0'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(newOrder.get(new OrderQty()).getValue()));
			e.set(new CumQty(0));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void cancelaNegocio(NewOrderSingle newOrder) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('1'));
			e.set(new ExecType('4'));
			e.set(new OrdStatus('4'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(newOrder.get(new OrderQty()).getValue()));
			e.set(new CumQty(0));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void acceptCancelOrderRequest(NewOrderSingle newOrder) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('1'));
			e.set(new ExecType('4'));
			e.set(new OrdStatus('4'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(newOrder.get(new OrderQty()).getValue()));
			e.set(new CumQty(0));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void rejectCancelOrderRequest(OrderCancelRequest newOrder) {
		OrderCancelReject c = new OrderCancelReject();
		try {
			c.setChar(434, '1');
			c.set(newOrder.get(new ClOrdID()));
			c.set(newOrder.get(new OrigClOrdID()));
			c.set(new OrdStatus('2'));
			c.set(newOrder.get(new OrderID()));
			Session.sendToTarget(c,session);
		} catch (FieldNotFound e) {
			e.printStackTrace();
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
	}

	@Override
	public void solicitaAlteracao(Order alterada) {
		// TODO Auto-generated method stub
		
	}

	public void acceptReplace(OrderCancelReplaceRequest rr) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(new AvgPx(0));
			e.set(new CumQty(0));
			e.set(new OrigClOrdID(rr.get(new ClOrdID()).getValue()));
			e.set(rr.get(new ClOrdID()));
			e.set(new OrderID(rr.get(new OrderID()).getValue()+"UPDATED"));
			e.set(new OrdStatus('0'));
			e.set(new ExecTransType('0'));
			e.set(new ExecType('5'));
			e.set(new LeavesQty(rr.get(new OrderQty()).getValue()));
			e.set(rr.get(new Symbol()));
			e.set(rr.get(new Side()));
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}

	public void rejectReplace(OrderCancelReplaceRequest newOrder) {
		OrderCancelReject c = new OrderCancelReject();
		try {
			c.set(newOrder.get(new ClOrdID()));
			c.set(newOrder.get(new OrigClOrdID()));
			c.set(new OrdStatus('2'));
			c.set(newOrder.get(new OrderID()));
			c.setChar(434, '2');
			Session.sendToTarget(c,session);
		} catch (FieldNotFound e) {
			e.printStackTrace();
		} catch (SessionNotFound e) {
			e.printStackTrace();
		}
		
	}

	public void rejectOrder(NewOrderSingle newOrder) {
		execID++;
		ExecutionReport e = new ExecutionReport();
		e.set(new OrderID("FAKE"+execID));
		try {
			e.set(newOrder.get(new ClOrdID()));
			e.set(new ExecID("FAKE-EXEC"+execID));
			e.set(newOrder.get(new Symbol()));
			e.set(new ExecTransType('0'));
			e.set(new ExecType('8'));
			e.set(new OrdStatus('0'));
			e.set(newOrder.get(new Side()));
			e.set(new AvgPx(0));
			e.set(new LeavesQty(newOrder.get(new OrderQty()).getValue()));
			e.set(new CumQty(0));
			
			Session.sendToTarget(e,session);
		} catch (FieldNotFound e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SessionNotFound e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
	}
}
